package com.lf.util;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by 王小红 on 2017/5/16.
 */
public class ImageUtils {
    private int _size = 20;
    private String _bgPath = "/data/img/bg.png";
    //private String _bgPath = "/admin/img/bg.png";
    //    private String _bgPath = "D:\\bg.jpg";

    // 定义一个私有构造方法
    private ImageUtils() {

    }

    //定义一个静态私有变量(不初始化，不使用final关键字，使用volatile保证了多线程访问时instance变量的可见性，避免了instance初始化时其他变量属性还没赋值完时，被另外线程调用)
    private static volatile ImageUtils instance;

    //定义一个共有的静态方法，返回该类型实例
    public static ImageUtils getIstance() {
        // 对象实例化时与否判断（不使用同步代码块，instance不等于null时，直接返回对象，提高运行效率）
        if (instance == null) {
            //同步代码块（对象未初始化时，使用同步代码块，保证多线程访问时对象在第一次创建后，不再重复被创建）
            synchronized (ImageUtils.class) {
                //未初始化，则初始instance变量
                if (instance == null) {
                    instance = new ImageUtils();
                }
            }
        }
        return instance;
    }

    /**
     * 生成二维码+背景+文字
     *
     * @param url 二维码内容地址
     * @param id  显示的用户ID
     * @return base64的图片
     */
    public String GetQR_BASE64(String url, String id) {//将图片文件转化为字节数组字符串，并对其进行Base64编码处理
        InputStream in;
        byte[] data = null;
        //读取图片字节数组
        try {
            in = this.gQR(url, id);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);//返回Base64编码过的字节数组字符串
    }

    /**
     * 生成二维码+背景
     *
     * @param url
     * @return
     */
    public String GetQR_BASE64(String url) {
        //将图片文件转化为字节数组字符串，并对其进行Base64编码处理
        InputStream in;
        byte[] data = null;
        //读取图片字节数组
        try {
            in = gpayQR(url);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);//返回Base64编码过的字节数组字符串
    }


    /**
     * 生成二维码
     *
     * @param url
     * @return
     */
    public String ONLYQR_BASE64(String url) {
        //将图片文件转化为字节数组字符串，并对其进行Base64编码处理
        InputStream in;
        byte[] data = null;
        //读取图片字节数组
        try {
            in = gQR(url);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);//返回Base64编码过的字节数组字符串
    }


    private InputStream gpayQR(String url) {
        try {
            BufferedImage qrImg = this.qrCodeCommon(url);//二维码
            BufferedImage bgImg = ImageIO.read(new File(_bgPath));//背景
            //bgImg = this.createPicTwo2(50,230,bgImg,qrImg);//拼接1
            //bgImg = this.createPicTwo2(50,210,bgImg,strImg);//拼接2
            bgImg = this.createPicTwo2(192, 540, bgImg, qrImg);//拼接1
//            bgImg = this.createPicTwo2(0, 0, bgImg, qrImg);//拼接1
//            ImageIO.write(bgImg, "png", new File("D:\\out.png"));
//            System.out.println("out over!!");
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(bgImg, "png", os);
            InputStream is = new ByteArrayInputStream(os.toByteArray());
            return is;
            // 生成二维码QRCode图片
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        ImageUtils.getIstance().GetQR_BASE64("www.baidu.com");
    }

    private InputStream gQR(String url, String id) {
        try {
            BufferedImage qrImg = this.qrCodeCommon(url);//二维码
            BufferedImage strImg = this.createImage(id, new Font("黑体", Font.BOLD, 15), 140, 17);//文字
            BufferedImage bgImg = ImageIO.read(new File(_bgPath));//背景
            //bgImg = this.createPicTwo2(50,230,bgImg,qrImg);//拼接1
            //bgImg = this.createPicTwo2(50,210,bgImg,strImg);//拼接2
            bgImg = this.createPicTwo2(122, 360, bgImg, qrImg);//拼接1
            bgImg = this.createPicTwo2(150, 500, bgImg, strImg);//拼接2
            //ImageIO.write(bgImg, "png", new File("D:\\out.png"));
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(bgImg, "png", os);
            InputStream is = new ByteArrayInputStream(os.toByteArray());
            return is;
            // 生成二维码QRCode图片
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private InputStream gQR(String url) {
        try {
            BufferedImage qrImg = this.qrCodeCommon(url);//二维码
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(qrImg, "png", os);
            InputStream is = new ByteArrayInputStream(os.toByteArray());
            return is;
            // 生成二维码QRCode图片
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 生成二维码(QRCode)图片的公共方法
     *
     * @param content 存储内容
     * @return 二维码的 BufferedImage
     */
//    private BufferedImage qrCodeCommon(String content) {
//        BufferedImage bufImg = null;
//        try {
//            Qrcode qrcodeHandler = new Qrcode();
//            // 设置二维码排错率，可选L(7%)、M(15%)、Q(25%)、H(30%)，排错率越高可存储的信息越少，但对二维码清晰度的要求越小
//            qrcodeHandler.setQrcodeErrorCorrect('M');
//            qrcodeHandler.setQrcodeEncodeMode('B');
//            // 设置设置二维码尺寸，取值范围1-40，值越大尺寸越大，可存储的信息越大
//            qrcodeHandler.setQrcodeVersion(_size);
//            // 获得内容的字节数组，设置编码格式
//            byte[] contentBytes = content.getBytes("utf-8");
//            // 图片尺寸
//            int imgSize = 67 + 12 * (_size - 1);
//            bufImg = new BufferedImage(imgSize, imgSize, BufferedImage.TYPE_INT_RGB);
//            Graphics2D gs = bufImg.createGraphics();
//            // 设置背景颜色
//            gs.setBackground(Color.WHITE);
//            gs.clearRect(0, 0, imgSize, imgSize);
//            // 设定图像颜色> BLACK
//            gs.setColor(Color.BLACK);
//            // 设置偏移量，不设置可能导致解析出错
//            int pixoff = 2;
//            // 输出内容> 二维码
//            if (contentBytes.length > 0 && contentBytes.length < 800) {
//                boolean[][] codeOut = qrcodeHandler.calQrcode(contentBytes);
//                for (int i = 0; i < codeOut.length; i++) {
//                    for (int j = 0; j < codeOut.length; j++) {
//                        if (codeOut[j][i]) {
//                            gs.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3);
//                        }
//                    }
//                }
//            } else {
//                throw new Exception("QRCode content bytes length = " + contentBytes.length + " not in [0, 800].");
//            }
//            gs.dispose();
//            bufImg.flush();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return bufImg;
//    }


    /**
     * 生成二维码(zxing)图片的公共方法
     *
     * @param content 存储内容
     * @return 二维码的 BufferedImage
     */
    private BufferedImage qrCodeCommon(String content) {
        BufferedImage bufImg = null;
        try {
            int width = 300; // 图像宽度
            int height = 300; // 图像高度
            Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.MARGIN, 1);
            BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
                    BarcodeFormat.QR_CODE, width, height, hints);// 生成矩阵
            bufImg = MatrixToImageWriter.toBufferedImage(bitMatrix);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bufImg;
    }


    /**
     * @param str
     * @param font
     * @param width
     * @param height
     * @return 返回的是文字的 BufferedImage
     * @throws Exception
     */
    private BufferedImage createImage(String str, Font font,
                                      Integer width, Integer height) throws Exception {
        // 创建图片
        BufferedImage image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_ARGB);
        Graphics g = image.getGraphics();
        g.setClip(0, 0, width, height);
        g.setColor(Color.white);
        g.setColor(new Color(0.87F, 0.192F, 0.1294F, 0.0f));
        g.fillRect(0, 0, width, height);// 先用黑色填充整张图片,也就是背景
        g.setColor(Color.white);// 在换成黑色
        g.setFont(font);// 设置画笔字体
        /** 用于获得垂直居中y */
        Rectangle clip = g.getClipBounds();
        FontMetrics fm = g.getFontMetrics(font);
        int ascent = fm.getAscent();
        int descent = fm.getDescent();
        int y = (clip.height - (ascent + descent)) / 2 + ascent;
        g.drawString(str, 0, y);// 画出字符串
        g.dispose();
        return image;
        //ImageIO.write(image, "png", outFile);// 输出png图片
    }

    /**
     * @param x
     * @param y
     * @param bg  背景
     * @param add
     * @return 合成后的 BufferedImage
     */
    private BufferedImage createPicTwo2(int x, int y, BufferedImage bg, BufferedImage add) {
        try {
            //读取第一张图片
            BufferedImage ImageOne1 = bg;
            int width = ImageOne1.getWidth();//图片宽度
            int height = ImageOne1.getHeight();//图片高度
            //从图片中读取RGB
            int[] ImageArrayOne1 = new int[width * height];
            ImageArrayOne1 = ImageOne1.getRGB(0, 0, width, height, ImageArrayOne1, 0, width);

            //对第二张图片做相同的处理
            BufferedImage ImageTwo = add;
            int widthTwo = (int) (ImageTwo.getWidth());//图片宽度

            int heightTwo = (int) (ImageTwo.getHeight());//图片高度
            int[] ImageArrayTwo = new int[widthTwo * heightTwo];
            ImageArrayTwo = ImageTwo.getRGB(0, 0, widthTwo, heightTwo, ImageArrayTwo, 0, widthTwo);
            //生成新图片
            BufferedImage ImageNew = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            ImageNew.setRGB(0, 0, width, height, ImageArrayOne1, 0, width);//设置左半部分的RGB
            ImageNew.setRGB(x, y, widthTwo, heightTwo, ImageArrayTwo, 0, widthTwo);//设置右半部分的RGB
            //ImageNew.setRGB(x,y,width3,height3,ImageArrayOne3,0,widthTwo);//设置右3半部分的RGB
//            File outFile = new File("d:\\out.png");
            return ImageNew;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


}